/*
    This file is part of Epoch <http://code.google.com/p/epoch/>.
    
    Copyright (C) 2011  Adam Meily <meily.adam@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


/*
 * hello        version     ssl list    requires ssl
 * get-delta    id          sig
 * delta
 * get-full     id
 * full         filename    id
 * get-ls       parent
 * ls
 *     type="{file,directory}"
 *          "file" size="quint64" last-modified="ts"
 *          "directory" path="/some/thing"
 */

/*
 * 
 */
#ifndef EPOCHPROTOCOL_H
#define EPOCHPROTOCOL_H

#include <QtNetwork/QSslSocket>
#include <QtCore/QStringList>
#include <QtCore/QList>
#include <QtCore/QString>
#include "Response.h"
#include "Request.h"
#include "NodeConfig.h"
#include "Epoch.h"

#define EPOCH_PROTOCOL_VERSION      0x061907

class Protocol : public QObject
{
    Q_OBJECT
public:
    enum Role
    {
        ServerRole,
        ClientRole
    };
    
    Protocol(int socket, Role role, const NodeConfig& config);
    virtual ~Protocol();

    Role role() const;
    bool messagePreprocess() const;

    const NodeConfig& localConfig() const;
    const NodeConfig* remoteConfig() const;

    int closeConnection();
    int handshake();

protected slots:
    void onReadReady();
    void onEncryptionReady();
    void onSocketError(QAbstractSocket::SocketError error);
    void onDisconnectSlot();

protected:
    virtual void onRequest(const Request& request) { };
    virtual void onResponse(const Response& response) { };
    virtual void onRawMessage(const QByteArray& raw) { };
    virtual void onDisconnect() { };
    virtual void onHandshakeComplete() { };
    
    qint64 write(const Message& msg);
    qint64 write(const QByteArray& raw);
    
    void stopMessagePreprocess();
    void resumeMessagePreprocess();
    int dispatch();
    
    //int dispatch(const QString& op, const MessageArgs& args, MessageFlags flags);

private:
    //int processHandshake(const Request& req);
    //int processHandshake(const Response& res);
    int processHandshake(const Message& msg);
    bool m_readLock;
    
    
    NodeConfig m_localConfig;
    NodeConfig *m_remoteConfig;

    QSslSocket m_socket;
    Role m_role;
    bool m_messagePreprocess;
    
    QStringList m_buffer;
};

QByteArray operator+(const QByteArray& buffer, const Record& record);
QByteArray& operator+=(QByteArray& buffer, const Record& record);
void append(QByteArray& buffer, const Record& record);

#endif // EPOCHPROTOCOL_H
